home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / boot / czesc_2 / toolmanager / source / prefs / menuwindow.c < prev    next >
C/C++ Source or Header  |  1993-05-15  |  13KB  |  505 lines

  1. /*
  2.  * menuwindow.c  V2.1
  3.  *
  4.  * menu edit window handling
  5.  *
  6.  * (c) 1990-1993 Stefan Becker
  7.  */
  8.  
  9. #include "ToolManagerConf.h"
  10.  
  11. /* Menu node */
  12. struct MenuNode {
  13.                   struct Node  mn_Node;
  14.                   char        *mn_Exec;
  15.                   char        *mn_Sound;
  16.                  };
  17.  
  18. /* Window data */
  19. static struct Gadget *gl;             /* Gadget list */
  20. static struct Window *w;              /* Window */
  21. static struct MsgPort *wp;            /* Window user port */
  22. static UWORD ww,wh;                   /* Window size */
  23. static struct MenuNode *CurrentNode;
  24. static ULONG CurrentGadgetNum;
  25. static BOOL ReqOpen;
  26. static struct Requester DummyReq;
  27. #define WINDOW_IDCMP (IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW|BUTTONIDCMP|\
  28.                       STRINGIDCMP|TEXTIDCMP|IDCMP_VANILLAKEY)
  29.  
  30. /* Gadget data */
  31. #define GAD_NAME_STR  0
  32. #define GAD_EXEC_BUT  1
  33. #define GAD_EXEC_TXT  2
  34. #define GAD_SOUND_BUT 3
  35. #define GAD_SOUND_TXT 4
  36. #define GAD_OK        5
  37. #define GAD_CANCEL    6
  38. #define GADGETS       7
  39. static struct GadgetData gdata[GADGETS];
  40.  
  41. /* Gadget tags */
  42. static struct TagItem nametags[]={GTST_String,   NULL,
  43.                                   GTST_MaxChars, SGBUFLEN,
  44.                                   TAG_DONE};
  45.  
  46. static struct TagItem exectags[]={GTTX_Text,   NULL,
  47.                                   GTTX_Border, TRUE,
  48.                                   TAG_DONE};
  49.  
  50. static struct TagItem soundtags[]={GTTX_Text,   NULL,
  51.                                    GTTX_Border, TRUE,
  52.                                    TAG_DONE};
  53.  
  54. /* Gadget vanilla key data */
  55. #define KEY_NAME   0
  56. #define KEY_EXEC   1
  57. #define KEY_SOUND  2
  58. #define KEY_OK     3
  59. #define KEY_CANCEL 4
  60. static char KeyArray[KEY_CANCEL+1];
  61.  
  62. /* Init menu edit window */
  63. void InitMenuEditWindow(UWORD left, UWORD fheight)
  64. {
  65.  ULONG tmp,tmp2,maxw1,maxw2;
  66.  ULONG strheight=fheight+2;
  67.  struct GadgetData *gd;
  68.  
  69.  /* Init strings */
  70.  gdata[GAD_OK].name       =AppStrings[MSG_WINDOW_OK_GAD];
  71.  gdata[GAD_CANCEL].name   =AppStrings[MSG_WINDOW_CANCEL_GAD];
  72.  
  73.  /* Calculate maximum label width for string gadgets */
  74.  maxw1=TextLength(&TmpRastPort,AppStrings[MSG_WINDOW_NAME_GAD],
  75.                   strlen(AppStrings[MSG_WINDOW_NAME_GAD]));
  76.  tmp=TextLength(&TmpRastPort,AppStrings[MSG_WINDOW_EXEC_GAD],
  77.                 strlen(AppStrings[MSG_WINDOW_EXEC_GAD]))+2*INTERWIDTH;
  78.  if (tmp > maxw1) maxw1=tmp;
  79.  tmp=TextLength(&TmpRastPort,AppStrings[MSG_WINDOW_SOUND_GAD],
  80.                 strlen(AppStrings[MSG_WINDOW_SOUND_GAD]))+2*INTERWIDTH;
  81.  if (tmp > maxw1) maxw1=tmp;
  82.  maxw1+=INTERWIDTH;
  83.  
  84.  /* Calculate minimal string gadget width */
  85.  ww=TextLength(&TmpRastPort,AppStrings[MSG_MENUWIN_NEWNAME],
  86.                strlen(AppStrings[MSG_MENUWIN_NEWNAME]))+
  87.     maxw1+3*INTERWIDTH;
  88.  
  89.  /* Calculate button gadgets width */
  90.  gd=&gdata[GAD_OK];
  91.  maxw2=TextLength(&TmpRastPort,gd->name,strlen(gd->name));
  92.  gd++;
  93.  if ((tmp=TextLength(&TmpRastPort,gd->name,strlen(gd->name))) > maxw2)
  94.   maxw2=tmp;
  95.  maxw2+=2*INTERWIDTH;
  96.  if ((tmp=2*(maxw2+INTERWIDTH)) > ww) ww=tmp;
  97.  
  98.  /* window height */
  99.  wh=4*fheight+5*INTERHEIGHT+6;
  100.  
  101.  /* Init gadgets */
  102.  gd=gdata;
  103.  tmp=WindowTop+INTERHEIGHT;
  104.  tmp2=ww-maxw1-INTERWIDTH;
  105.  
  106.  /* Name string gadget */
  107.  gd->name=AppStrings[MSG_WINDOW_NAME_GAD];
  108.  gd->type=STRING_KIND;
  109.  gd->flags=PLACETEXT_LEFT;
  110.  gd->tags=nametags;
  111.  gd->left=maxw1+left;
  112.  gd->top=tmp;
  113.  gd->width=tmp2;
  114.  gd->height=strheight;
  115.  tmp+=strheight+INTERHEIGHT;
  116.  
  117.  /* Exec object button gadget */
  118.  gd++;
  119.  gd->name=AppStrings[MSG_WINDOW_EXEC_GAD];
  120.  gd->type=BUTTON_KIND;
  121.  gd->flags=PLACETEXT_IN;
  122.  gd->left=left;
  123.  gd->top=tmp;
  124.  gd->width=maxw1-INTERWIDTH;
  125.  gd->height=strheight;
  126.  
  127.  /* Exec object text gadget */
  128.  gd++;
  129.  gd->type=TEXT_KIND;
  130.  gd->tags=exectags;
  131.  gd->left=maxw1+left;
  132.  gd->top=tmp;
  133.  gd->width=tmp2;
  134.  gd->height=strheight;
  135.  tmp+=strheight+INTERHEIGHT;
  136.  
  137.  /* Sound object button gadget */
  138.  gd++;
  139.  gd->name=AppStrings[MSG_WINDOW_SOUND_GAD];
  140.  gd->type=BUTTON_KIND;
  141.  gd->flags=PLACETEXT_IN;
  142.  gd->left=left;
  143.  gd->top=tmp;
  144.  gd->width=maxw1-INTERWIDTH;
  145.  gd->height=strheight;
  146.  
  147.  /* Sound object text gadget */
  148.  gd++;
  149.  gd->type=TEXT_KIND;
  150.  gd->tags=soundtags;
  151.  gd->left=maxw1+left;
  152.  gd->top=tmp;
  153.  gd->width=tmp2;
  154.  gd->height=strheight;
  155.  tmp+=strheight+INTERHEIGHT;
  156.  
  157.  /* OK button gadget */
  158.  gd++;
  159.  gd->type=BUTTON_KIND;
  160.  gd->flags=PLACETEXT_IN;
  161.  gd->left=left;
  162.  gd->top=tmp;
  163.  gd->width=maxw2;
  164.  gd->height=fheight;
  165.  
  166.  /* Cancel button gadget */
  167.  gd++;
  168.  gd->type=BUTTON_KIND;
  169.  gd->flags=PLACETEXT_IN;
  170.  gd->left=ww-maxw2-INTERWIDTH+left;
  171.  gd->top=tmp;
  172.  gd->width=maxw2;
  173.  gd->height=fheight;
  174.  
  175.  /* Init vanilla key array */
  176.  KeyArray[KEY_NAME]  =FindVanillaKey(gdata[GAD_NAME_STR].name);
  177.  KeyArray[KEY_EXEC]  =FindVanillaKey(gdata[GAD_EXEC_BUT].name);
  178.  KeyArray[KEY_SOUND] =FindVanillaKey(gdata[GAD_SOUND_BUT].name);
  179.  KeyArray[KEY_OK]    =FindVanillaKey(gdata[GAD_OK].name);
  180.  KeyArray[KEY_CANCEL]=FindVanillaKey(gdata[GAD_CANCEL].name);
  181.  
  182.  /* Init dummy requester structure */
  183.  InitRequester(&DummyReq);
  184. }
  185.  
  186. /* Free menu node */
  187. void FreeMenuNode(struct Node *node)
  188. {
  189.  struct MenuNode *mn=(struct MenuNode *) node;
  190.  char *s;
  191.  
  192.  if (s=mn->mn_Node.ln_Name) free(s);
  193.  if (s=mn->mn_Exec) free(s);
  194.  if (s=mn->mn_Sound) free(s);
  195.  
  196.  /* Free node */
  197.  FreeMem(mn,sizeof(struct MenuNode));
  198. }
  199.  
  200. /* Copy menu node */
  201. struct Node *CopyMenuNode(struct Node *node)
  202. {
  203.  struct MenuNode *mn,*orignode=(struct MenuNode *) node;
  204.  
  205.  /* Alloc memory for menu node */
  206.  if (mn=AllocMem(sizeof(struct MenuNode),MEMF_PUBLIC|MEMF_CLEAR)) {
  207.  
  208.   /* Got an old node? */
  209.   if (orignode) {
  210.    /* Yes, copy it */
  211.    if ((!orignode->mn_Node.ln_Name || (mn->mn_Node.ln_Name=
  212.                                         strdup(orignode->mn_Node.ln_Name))) &&
  213.        (!orignode->mn_Exec || (mn->mn_Exec=strdup(orignode->mn_Exec))) &&
  214.        (!orignode->mn_Sound || (mn->mn_Sound=strdup(orignode->mn_Sound))))
  215.     return(mn);
  216.   } else
  217.    /* No, set defaults */
  218.    if (mn->mn_Node.ln_Name=strdup(AppStrings[MSG_MENUWIN_NEWNAME]))
  219.     /* Return pointer to new node */
  220.     return(mn);
  221.  
  222.   FreeMenuNode((struct Node *) mn);
  223.  }
  224.  /* Call failed */
  225.  return(NULL);
  226. }
  227.  
  228. /* Create menu node from string */
  229. struct Node *CreateMenuNode(char *name)
  230. {
  231.  struct MenuNode *mn;
  232.  
  233.  /* Alloc memory for menu node */
  234.  if (mn=AllocMem(sizeof(struct MenuNode),MEMF_PUBLIC|MEMF_CLEAR)) {
  235.  
  236.   /* Init node */
  237.   if ((mn->mn_Node.ln_Name=strdup(name)) &&
  238.       (mn->mn_Exec=strdup(name)))
  239.    /* All OK. */
  240.    return(mn);
  241.  
  242.   FreeMenuNode((struct Node *) mn);
  243.  }
  244.  /* Call failed */
  245.  return(NULL);
  246. }
  247.  
  248. /* Activate name string gadget */
  249. static void ActivateNameGadget(void)
  250. {
  251.  ActivateGadget(gdata[GAD_NAME_STR].gadget,w,NULL);
  252. }
  253.  
  254. /* Open menu edit window */
  255. BOOL OpenMenuEditWindow(struct Node *node, struct Window *parent)
  256. {
  257.  /* Copy node */
  258.  if (CurrentNode=(struct MenuNode *) CopyMenuNode(node)) {
  259.   /* Set tags */
  260.   nametags[0].ti_Data=(ULONG) CurrentNode->mn_Node.ln_Name;
  261.   exectags[0].ti_Data=(ULONG) CurrentNode->mn_Exec;
  262.   soundtags[0].ti_Data=(ULONG) CurrentNode->mn_Sound;
  263.  
  264.   /* Create gadgets */
  265.   if (gl=CreateGadgetList(gdata,GADGETS)) {
  266.    /* Open window */
  267.    if (w=OpenWindowTags(NULL,WA_Left,        parent->LeftEdge,
  268.                              WA_Top,         parent->TopEdge+WindowTop,
  269.                              WA_InnerWidth,  ww,
  270.                              WA_InnerHeight, wh,
  271.                              WA_AutoAdjust,  TRUE,
  272.                              WA_Title,       AppStrings[MSG_MENUWIN_TITLE],
  273.                              WA_PubScreen,   PublicScreen,
  274.                              WA_Flags,       WFLG_CLOSEGADGET|WFLG_DRAGBAR|
  275.                                              WFLG_DEPTHGADGET|WFLG_RMBTRAP|
  276.                                              WFLG_ACTIVATE,
  277.                              TAG_DONE)) {
  278.     /* Add gadgets to window */
  279.     AddGList(w,gl,(UWORD) -1,(UWORD) -1,NULL);
  280.     RefreshGList(gl,w,NULL,(UWORD) -1);
  281.     GT_RefreshWindow(w,NULL);
  282.  
  283.     /* Activate name string gadget */
  284.     ActivateNameGadget();
  285.  
  286.     /* Set local variables */
  287.     w->UserPort=IDCMPPort;
  288.     w->UserData=(BYTE *) HandleMenuEditWindowIDCMP;
  289.     ModifyIDCMP(w,WINDOW_IDCMP);
  290.     CurrentWindow=w;
  291.     ReqOpen=FALSE;
  292.  
  293.     /* All OK. */
  294.     return(TRUE);
  295.    }
  296.    FreeGadgets(gl);
  297.   }
  298.   FreeMenuNode((struct Node *) CurrentNode);
  299.  }
  300.  /* Call failed */
  301.  return(FALSE);
  302. }
  303.  
  304. /* Close menu edit window */
  305. static void CloseMenuEditWindow(void)
  306. {
  307.  /* Free resources */
  308.  RemoveGList(w,gl,(UWORD) -1);
  309.  CloseWindowSafely(w);
  310.  FreeGadgets(gl);
  311. }
  312.  
  313. /* Exec & Sound gadget function */
  314. static void TextButtonGadgetFunc(ULONG gadnum, ULONG listnum)
  315. {
  316.  if (!ReqOpen) {
  317.   /* Save gadget number */
  318.   CurrentGadgetNum=gadnum;
  319.  
  320.   /* Open list requester */
  321.   if (OpenListRequester(listnum,w)) {
  322.    /* Disable window */
  323.    DisableWindow(w,&DummyReq);
  324.  
  325.    /* Set update function */
  326.    UpdateWindow=UpdateMenuEditWindow;
  327.    ReqOpen=TRUE;
  328.   }
  329.  }
  330. }
  331.  
  332. /* OK gadget function */
  333. static struct Node *OKGadgetFunc(void)
  334. {
  335.  struct Node *rc;
  336.  char *s;
  337.  
  338.  /* Free old string */
  339.  if (s=CurrentNode->mn_Node.ln_Name) free(s);
  340.  
  341.  /* Duplicate new string */
  342.  if ((CurrentNode->mn_Node.ln_Name=
  343.        DuplicateBuffer(gdata[GAD_NAME_STR].gadget)) != (char *) -1)
  344.   rc=(struct Node *) CurrentNode;
  345.  else {
  346.   /* Couldn't copy strings */
  347.   rc=(struct Node *) -1;
  348.   FreeMenuNode((struct Node *) CurrentNode);
  349.  }
  350.  return(rc);
  351. }
  352.  
  353. /* Handle menu edit window IDCMP events */
  354. void *HandleMenuEditWindowIDCMP(struct IntuiMessage *msg)
  355. {
  356.  struct Node *NewNode=NULL;
  357.  
  358.  /* Which IDCMP class? */
  359.  switch (msg->Class) {
  360.   case IDCMP_CLOSEWINDOW:   NewNode=(struct Node *) -1;
  361.                             FreeMenuNode((struct Node *) CurrentNode);
  362.                             break;
  363.   case IDCMP_REFRESHWINDOW: GT_BeginRefresh(w);
  364.                             GT_EndRefresh(w,TRUE);
  365.                             break;
  366.   case IDCMP_GADGETUP:
  367.    switch (((struct Gadget *) msg->IAddress)->GadgetID) {
  368.     case GAD_EXEC_BUT:  TextButtonGadgetFunc(GAD_EXEC_TXT,LISTREQ_EXEC);
  369.                         break;
  370.     case GAD_SOUND_BUT: TextButtonGadgetFunc(GAD_SOUND_TXT,LISTREQ_SOUND);
  371.                         break;
  372.     case GAD_OK:        NewNode=OKGadgetFunc();
  373.                         break;
  374.     case GAD_CANCEL:    NewNode=(struct Node *) -1;
  375.                         FreeMenuNode((struct Node *) CurrentNode);
  376.                         break;
  377.    }
  378.    break;
  379.   case IDCMP_VANILLAKEY:
  380.    switch (MatchVanillaKey(msg->Code,KeyArray)) {
  381.     case KEY_NAME:   ActivateNameGadget();
  382.                      break;
  383.     case KEY_EXEC:   TextButtonGadgetFunc(GAD_EXEC_TXT,LISTREQ_EXEC);
  384.                      break;
  385.     case KEY_SOUND:  TextButtonGadgetFunc(GAD_SOUND_TXT,LISTREQ_SOUND);
  386.                      break;
  387.     case KEY_OK:     NewNode=OKGadgetFunc();
  388.                      break;
  389.     case KEY_CANCEL: NewNode=(struct Node *) -1;
  390.                      FreeMenuNode((struct Node *) CurrentNode);
  391.                      break;
  392.    }
  393.    break;
  394.  }
  395.  
  396.  /* Close window? */
  397.  if (NewNode) {
  398.   /* Yes. But first reply message!!! */
  399.   GT_ReplyIMsg(msg);
  400.   CloseMenuEditWindow();
  401.  }
  402.  
  403.  return(NewNode);
  404. }
  405.  
  406. /* Update Menu edit window */
  407. void UpdateMenuEditWindow(void *data)
  408. {
  409.  /* Got data? */
  410.  if (data != LREQRET_CANCEL) {
  411.   char *new;
  412.  
  413.   /* Selected something? */
  414.   new=(data == LREQRET_NOSELECT) ? NULL : ((struct Node *) data)->ln_Name;
  415.  
  416.   /* Duplicate name */
  417.   if (!new || (new=strdup(new))) {
  418.    char *old;
  419.  
  420.    /* Exec object? */
  421.    if (CurrentGadgetNum==GAD_EXEC_TXT) {
  422.     /* Yes. Set new Exec name */
  423.     old=CurrentNode->mn_Exec;
  424.     CurrentNode->mn_Exec=new;
  425.    } else {
  426.     /* No. Set new Sound name */
  427.     old=CurrentNode->mn_Sound;
  428.     CurrentNode->mn_Sound=new;
  429.    }
  430.  
  431.    /* Free old string */
  432.    if (old) free(old);
  433.  
  434.    /* Set new text */
  435.    GT_SetGadgetAttrs(gdata[CurrentGadgetNum].gadget,w,NULL,GTTX_Text,new,
  436.                                                            TAG_DONE);
  437.   }
  438.  }
  439.  
  440.  /* Enable window */
  441.  EnableWindow(w,&DummyReq,WINDOW_IDCMP);
  442.  
  443.  /* Restore update function pointer */
  444.  UpdateWindow=UpdateMainWindow;
  445.  CurrentWindow=w;
  446.  ReqOpen=FALSE;
  447. }
  448.  
  449. /* Read TMMO IFF chunk into Menu node */
  450. struct Node *ReadMenuNode(UBYTE *buf)
  451. {
  452.  struct MenuNode *mn;
  453.  
  454.  /* Allocate memory for node */
  455.  if (mn=AllocMem(sizeof(struct MenuNode),MEMF_PUBLIC|MEMF_CLEAR)) {
  456.   struct MenuPrefsObject *mpo=(struct MenuPrefsObject *) buf;
  457.   ULONG sbits=mpo->mpo_StringBits;
  458.   UBYTE *ptr=(UBYTE *) &mpo[1];
  459.  
  460.   if ((!(sbits & MOPO_NAME) || (mn->mn_Node.ln_Name=GetConfigStr(&ptr))) &&
  461.       (!(sbits & MOPO_EXEC) || (mn->mn_Exec=GetConfigStr(&ptr))) &&
  462.       (!(sbits & MOPO_SOUND) || (mn->mn_Sound=GetConfigStr(&ptr))))
  463.    /* All OK. */
  464.    return(mn);
  465.  
  466.   /* Call failed */
  467.   FreeMenuNode((struct Node *) mn);
  468.  }
  469.  return(NULL);
  470. }
  471.  
  472. /* Write Menu node to TMMO IFF chunk */
  473. BOOL WriteMenuNode(struct IFFHandle *iff, UBYTE *buf, struct Node *node)
  474. {
  475.  struct MenuNode *mn=(struct MenuNode *) node;
  476.  struct MenuPrefsObject *mpo=(struct MenuPrefsObject *) buf;
  477.  ULONG sbits=0;
  478.  UBYTE *ptr=(UBYTE *) &mpo[1];
  479.  
  480.  /* Copy strings */
  481.  if (PutConfigStr(mn->mn_Node.ln_Name,&ptr)) sbits|=MOPO_NAME;
  482.  if (PutConfigStr(mn->mn_Exec,&ptr)) sbits|=MOPO_EXEC;
  483.  if (PutConfigStr(mn->mn_Sound,&ptr)) sbits|=MOPO_SOUND;
  484.  
  485.  /* set string bits */
  486.  mpo->mpo_StringBits=sbits;
  487.  
  488.  /* calculate length */
  489.  sbits=ptr-buf;
  490.  
  491.  DEBUG_PRINTF("chunk size %ld\n",sbits);
  492.  
  493.  /* Open chunk */
  494.  if (PushChunk(iff,0,ID_TMMO,sbits)) return(FALSE);
  495.  
  496.  /* Write chunk */
  497.  if (WriteChunkBytes(iff,buf,sbits)!=sbits) return(FALSE);
  498.  
  499.  /* Close chunk */
  500.  if (PopChunk(iff)) return(FALSE);
  501.  
  502.  /* All OK. */
  503.  return(TRUE);
  504. }
  505.